﻿using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels.Sockets;
using DotNetty.Transport.Channels;
using System.Net;
using DotNetty.Handlers.Logging;
using DotNetty.Codecs;
using System.Text;
using DotNetty.Buffers;

namespace SpecialDelimiterClient
{
    internal class Program
    {
        static async Task RunClientAsync()
        {
            var group = new MultithreadEventLoopGroup();

            try
            {
                Bootstrap bootstrap = new Bootstrap();
                bootstrap.Group(group)
                    .Channel<TcpSocketChannel>()
                    .Option(ChannelOption.TcpNodelay, true) // Option设置底层参数,这里设置基于TCP的socket它是没有延迟的
                    .Handler(new ActionChannelInitializer<ISocketChannel>(channel =>
                    {
                        // 如果不加String的编解码器,会报异常:unsupported message type: String (expected: IByteBuffer)
                        IChannelPipeline pipeline = channel.Pipeline;
                        pipeline.AddLast(new LoggingHandler(LogLevel.DEBUG));

                        // Unpooled:DotNetty自带的静态工具类,有关于byte字节的处理,生成/操作/删除/拷贝的一些静态方法等等.
                        IByteBuffer separator = Unpooled.CopiedBuffer(Encoding.UTF8.GetBytes("$_"));
                        // 使用:"$_"作为分隔符
                        pipeline.AddLast(new DelimiterBasedFrameDecoder(1024, separator));
                        pipeline.AddLast(new StringEncoder(Encoding.UTF8), new StringDecoder(Encoding.UTF8));

                        pipeline.AddLast(new DelimiterClientHandler());
                    }));

                IChannel bootstrapChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888));

                for (; ; )
                {
                    Console.WriteLine("请输入给服务端发送的内容(客户端退出,请输入:bye):");
                    string? line = Console.ReadLine();
                    // if (string.IsNullOrEmpty(line))
                    //     continue;

                    try
                    {
                        // $_作为分隔符
                        await bootstrapChannel.WriteAndFlushAsync(line + "$_");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }

                    // StringComparison.OrdinalIgnoreCase:忽略大小写
                    if (string.Equals("bye", line, StringComparison.OrdinalIgnoreCase))
                    {
                        await bootstrapChannel.CloseAsync();
                        break;
                    }
                }
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Task.WaitAll(group.ShutdownGracefullyAsync());
            }
        }

        static async Task Main(string[] args) => await RunClientAsync();
    }
}